# -*- coding: utf-8 -*-
# time: 2025/8/9 16:16
# file: views.py
# author: kai
# email: 1071664616@qq.com

"""
健康视图
"""
import time
import picologging as logging
from django.utils import timezone
from django.db import models
from django.core.cache import cache
from rest_framework import generics, permissions, views, status
from rest_framework.response import Response
from rest_framework.decorators import api_view, permission_classes
from rest_framework.serializers import ValidationError
from rest_framework.pagination import PageNumberPagination
from drf_spectacular.utils import extend_schema, OpenApiResponse, extend_schema_view
from rest_framework.parsers import MultiPartParser, FormParser
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.http import StreamingHttpResponse
import json

import os
from django.conf import settings

from .models import BodyRecord, Comment, Notice, SleepRecord, SportsRecord, EatingRecord, ScheduledTask, SensitiveWord, \
    HealthNews, Post, PostFavorite, PostLike, HealthReport
from .serializers import (
    BodyRecordSerializer, BodyRecordCreateSerializer,
    CommentSerializer, CommentCreateSerializer,
    EatingRecordSerializer, EatingRecordCreateSerializer,
    NoticeSerializer,
    SleepRecordSerializer, SleepRecordCreateSerializer,
    SportsRecordSerializer, SportsRecordCreateSerializer, ScheduledTaskSerializer, SensitiveWordCreateSerializer,
    SensitiveWordSerializer, HealthNewsSerializer, PostSerializer, PostCreateSerializer, PostFavoriteSerializer
)
from ..users.views import IsAdminUser
from ..users.models import User
from services.checker import SensitiveWordTrieDetector

# 创建logger实例
logger = logging.getLogger(__name__)

# 创建全局 Trie 树检测器实例
_trie_detector = None

def get_trie_detector():
    """获取全局 Trie 树敏感词检测器实例"""
    global _trie_detector
    if _trie_detector is None:
        _trie_detector = SensitiveWordTrieDetector()
        _trie_detector.initialize()
    return _trie_detector

def check_sensitive_words(content):
    """
    使用 Trie 树检查内容是否包含敏感词
    :param content: 要检查的文本内容
    :return: (是否包含敏感词, 敏感词列表)
    """
    detector = get_trie_detector()
    try:
        return detector.detect(content)
    except Exception as e:
        # 如果 Trie 树未初始化或出错，回退到基本检测方法
        print(f"Trie detection failed: {e}")
        return False, []


class IsAdminOrOwner(permissions.BasePermission):
    """
    通用权限类
    """
    def has_object_permission(self, request, view, obj):
        # 检查是否有 user_id 字段或者 user 关联字段
        if hasattr(obj, 'user_id'):
            user_id = obj.user_id
        elif hasattr(obj, 'user'):
            user_id = obj.user.id
        else:
            return False
            
        # 如果帖子状态为草稿，只有作者可以访问
        if hasattr(obj, 'status') and obj.status == 'draft':
            return user_id == request.user.id
        # 其他状态下，作者和管理员都可以访问
        else:
            return request.user.is_admin() or user_id == request.user.id

    def has_permission(self, request, view):
        # 对于列表视图和创建视图，只允许认证用户访问
        # 对于详情视图，has_object_permission 会进行更具体的检查
        return request.user and request.user.is_authenticated


# BodyRecord Views
@extend_schema_view(
    get=extend_schema(
        summary="获取身体指标记录列表",
        description="管理员可以看到所有记录，普通用户只能看到自己的记录",
        tags=['身体指标记录'],
        responses={
            200: BodyRecordSerializer(many=True),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    ),
    post=extend_schema(
        summary="创建身体指标记录",
        description="管理员可以为任意用户创建记录，普通用户只能为自己创建",
        tags=['身体指标记录'],
        request=BodyRecordCreateSerializer,
        responses={
            201: BodyRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    )
)
class BodyRecordListCreateView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return BodyRecordCreateSerializer
        return BodyRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以看到所有记录
        if user.is_admin():
            return BodyRecord.objects.all()
        # 普通用户只能看到自己的记录
        return BodyRecord.objects.filter(user_id=user.id)

    def perform_create(self, serializer):
        user = self.request.user
        user_id = serializer.validated_data.get('user_id', user.id)

        # 管理员可以为任意用户创建记录，普通用户只能为自己创建
        if user.is_admin() or user.id == user_id:
            serializer.save()
        else:
            raise ValidationError("您只能为自己创建身体指标记录")


@extend_schema_view(
    get=extend_schema(
        summary="获取身体指标记录详情",
        description="获取指定ID的身体指标记录详细信息",
        tags=['身体指标记录'],
        responses={
            200: BodyRecordSerializer,
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    put=extend_schema(
        summary="更新身体指标记录",
        description="完全更新身体指标记录信息",
        tags=['身体指标记录'],
        request=BodyRecordCreateSerializer,
        responses={
            200: BodyRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新身体指标记录",
        description="部分更新身体指标记录信息",
        tags=['身体指标记录'],
        request=BodyRecordCreateSerializer,
        responses={
            200: BodyRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    delete=extend_schema(
        summary="删除身体指标记录",
        description="删除指定ID的身体指标记录",
        tags=['身体指标记录'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    )
)
class BodyRecordDetailView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticated, IsAdminOrOwner]

    def get_serializer_class(self):
        if self.request.method in ['PUT', 'PATCH']:
            return BodyRecordCreateSerializer
        return BodyRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以操作所有记录
        if user.is_admin():
            return BodyRecord.objects.all()
        # 普通用户只能操作自己的记录
        return BodyRecord.objects.filter(user_id=user.id)


# Comment Views
@extend_schema_view(
    get=extend_schema(
        summary="获取评论列表",
        description="管理员可以看到所有评论，普通用户只能看到自己的评论",
        tags=['评论'],
        responses={
            200: CommentSerializer(many=True),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    ),
    post=extend_schema(
        summary="创建评论",
        description="管理员可以为任意用户创建评论，普通用户只能为自己创建",
        tags=['评论'],
        request=CommentCreateSerializer,
        responses={
            201: CommentSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    )
)
class CommentListCreateView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return CommentCreateSerializer
        return CommentSerializer

    def get_queryset(self):
        queryset = Comment.objects.all()
        # 支持按模块和关联ID过滤
        module = self.request.query_params.get('module', None)
        fid = self.request.query_params.get('fid', None)

        if module:
            queryset = queryset.filter(module=module)
        if fid:
            queryset = queryset.filter(fid=fid)
        return queryset

    def perform_create(self, serializer):
        user = self.request.user
        content = serializer.validated_data.get('content', '')

        # 检查评论内容中的敏感词（使用 Trie 树）
        has_sensitive, sensitive_words = check_sensitive_words(content)

        if has_sensitive:
            raise ValidationError(f"评论包含敏感词: {', '.join(sensitive_words)}")

        # 所有用户都可以创建评论，自动设置当前用户为评论者
        # serializer.validated_data['user_id'] = user.id
        serializer.save(user_id=user.id)


@extend_schema_view(
    get=extend_schema(
        summary="获取评论详情",
        description="获取指定ID的评论详细信息",
        tags=['评论'],
        responses={
            200: CommentSerializer,
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='评论不存在')
        }
    ),
    put=extend_schema(
        summary="更新评论",
        description="完全更新评论信息",
        tags=['评论'],
        request=CommentCreateSerializer,
        responses={
            200: CommentSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='评论不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新评论",
        description="部分更新评论信息",
        tags=['评论'],
        request=CommentCreateSerializer,
        responses={
            200: CommentSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='评论不存在')
        }
    ),
    delete=extend_schema(
        summary="删除评论",
        description="删除指定ID的评论",
        tags=['评论'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='评论不存在')
        }
    )
)
class CommentDetailView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticated, IsAdminOrOwner]

    def get_serializer_class(self):
        if self.request.method in ['PUT', 'PATCH']:
            return CommentCreateSerializer
        return CommentSerializer

    def get_queryset(self):
        # 所有认证用户都可以查看所有评论
        return Comment.objects.all()


# EatingRecord Views
@extend_schema_view(
    get=extend_schema(
        summary="获取饮食记录列表",
        description="管理员可以看到所有记录，普通用户只能看到自己的记录",
        tags=['饮食记录'],
        responses={
            200: EatingRecordSerializer(many=True),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    ),
    post=extend_schema(
        summary="创建饮食记录",
        description="管理员可以为任意用户创建记录，普通用户只能为自己创建",
        tags=['饮食记录'],
        request=EatingRecordCreateSerializer,
        responses={
            201: EatingRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    )
)
class EatingRecordListCreateView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return EatingRecordCreateSerializer
        return EatingRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以看到所有记录
        if user.is_admin():
            return EatingRecord.objects.all()
        # 普通用户只能看到自己的记录
        return EatingRecord.objects.filter(user_id=user.id)

    def perform_create(self, serializer):
        user = self.request.user
        user_id = serializer.validated_data.get('user_id', user.id)

        # 管理员可以为任意用户创建记录，普通用户只能为自己创建
        if user.is_admin() or user.id == user_id:
            serializer.save()
        else:
            raise ValidationError("您只能为自己创建饮食记录")


@extend_schema_view(
    get=extend_schema(
        summary="获取饮食记录详情",
        description="获取指定ID的饮食记录详细信息",
        tags=['饮食记录'],
        responses={
            200: EatingRecordSerializer,
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    put=extend_schema(
        summary="更新饮食记录",
        description="完全更新饮食记录信息",
        tags=['饮食记录'],
        request=EatingRecordCreateSerializer,
        responses={
            200: EatingRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新饮食记录",
        description="部分更新饮食记录信息",
        tags=['饮食记录'],
        request=EatingRecordCreateSerializer,
        responses={
            200: EatingRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    delete=extend_schema(
        summary="删除饮食记录",
        description="删除指定ID的饮食记录",
        tags=['饮食记录'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    )
)
class EatingRecordDetailView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticated, IsAdminOrOwner]

    def get_serializer_class(self):
        if self.request.method in ['PUT', 'PATCH']:
            return EatingRecordCreateSerializer
        return EatingRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以操作所有记录
        if user.is_admin():
            return EatingRecord.objects.all()
        # 普通用户只能操作自己的记录
        return EatingRecord.objects.filter(user_id=user.id)


# Notice Views (公告通常只读，不需要用户权限控制)
@extend_schema_view(
    get=extend_schema(
        summary="获取系统公告列表",
        description="获取所有系统公告",
        tags=['系统公告'],
        responses={
            200: NoticeSerializer(many=True),
            401: OpenApiResponse(description='未认证')
        }
    )
)
class NoticeListCreateView(generics.ListCreateAPIView):
    queryset = Notice.objects.all().order_by('-created_at')
    serializer_class = NoticeSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        if self.request.method == 'POST':
            # 创建公告需要管理员权限
            permission_classes = [permissions.IsAuthenticated, IsAdminUser]
        else:
            # 获取公告列表只需要认证
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]

    def perform_create(self, serializer):
        """
        创建公告时自动设置发布时间
        """
        # 如果没有提供发布时间，则使用当前时间
        if not serializer.validated_data.get('publish_time'):
            serializer.validated_data['publish_time'] = timezone.now().strftime('%Y-%m-%d %H:%M:%S')
        serializer.save()


@extend_schema_view(
    get=extend_schema(
        summary="获取系统公告详情",
        description="获取指定ID的系统公告详细信息",
        tags=['系统公告'],
        responses={
            200: NoticeSerializer,
            401: OpenApiResponse(description='未认证'),
            404: OpenApiResponse(description='公告不存在')
        }
    ),
    put=extend_schema(
        summary="更新系统公告",
        description="更新指定ID的系统公告信息",
        tags=['系统公告'],
        request=NoticeSerializer,
        responses={
            200: NoticeSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='公告不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新系统公告",
        description="部分更新指定ID的系统公告信息",
        tags=['系统公告'],
        request=NoticeSerializer,
        responses={
            200: NoticeSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='公告不存在')
        }
    ),
    delete=extend_schema(
        summary="删除系统公告",
        description="删除指定ID的系统公告",
        tags=['系统公告'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='公告不存在')
        }
    )
)
class NoticeDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Notice.objects.all()
    serializer_class = NoticeSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        if self.request.method in ['PUT', 'PATCH', 'DELETE']:
            # 更新和删除公告需要管理员权限
            permission_classes = [permissions.IsAuthenticated, IsAdminUser]
        else:
            # 获取公告详情只需要认证
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]


# SleepRecord Views
@extend_schema_view(
    get=extend_schema(
        summary="获取睡眠记录列表",
        description="管理员可以看到所有记录，普通用户只能看到自己的记录",
        tags=['睡眠记录'],
        responses={
            200: SleepRecordSerializer(many=True),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    ),
    post=extend_schema(
        summary="创建睡眠记录",
        description="管理员可以为任意用户创建记录，普通用户只能为自己创建",
        tags=['睡眠记录'],
        request=SleepRecordCreateSerializer,
        responses={
            201: SleepRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    )
)
class SleepRecordListCreateView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return SleepRecordCreateSerializer
        return SleepRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以看到所有记录
        if user.is_admin():
            return SleepRecord.objects.all()
        # 普通用户只能看到自己的记录
        return SleepRecord.objects.filter(user_id=user.id)

    def perform_create(self, serializer):
        user = self.request.user
        user_id = serializer.validated_data.get('user_id', user.id)

        # 管理员可以为任意用户创建记录，普通用户只能为自己创建
        if user.is_admin() or user.id == user_id:
            serializer.save()
        else:
            raise ValidationError("您只能为自己创建睡眠记录")


@extend_schema_view(
    get=extend_schema(
        summary="获取睡眠记录详情",
        description="获取指定ID的睡眠记录详细信息",
        tags=['睡眠记录'],
        responses={
            200: SleepRecordSerializer,
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    put=extend_schema(
        summary="更新睡眠记录",
        description="完全更新睡眠记录信息",
        tags=['睡眠记录'],
        request=SleepRecordCreateSerializer,
        responses={
            200: SleepRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新睡眠记录",
        description="部分更新睡眠记录信息",
        tags=['睡眠记录'],
        request=SleepRecordCreateSerializer,
        responses={
            200: SleepRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    delete=extend_schema(
        summary="删除睡眠记录",
        description="删除指定ID的睡眠记录",
        tags=['睡眠记录'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    )
)
class SleepRecordDetailView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticated, IsAdminOrOwner]

    def get_serializer_class(self):
        if self.request.method in ['PUT', 'PATCH']:
            return SleepRecordCreateSerializer
        return SleepRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以操作所有记录
        if user.is_admin():
            return SleepRecord.objects.all()
        # 普通用户只能操作自己的记录
        return SleepRecord.objects.filter(user_id=user.id)


# SportsRecord Views
@extend_schema_view(
    get=extend_schema(
        summary="获取运动记录列表",
        description="管理员可以看到所有记录，普通用户只能看到自己的记录",
        tags=['运动记录'],
        responses={
            200: SportsRecordSerializer(many=True),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    ),
    post=extend_schema(
        summary="创建运动记录",
        description="管理员可以为任意用户创建记录，普通用户只能为自己创建",
        tags=['运动记录'],
        request=SportsRecordCreateSerializer,
        responses={
            201: SportsRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    )
)
class SportsRecordListCreateView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return SportsRecordCreateSerializer
        return SportsRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以看到所有记录
        if user.is_admin():
            return SportsRecord.objects.all()
        # 普通用户只能看到自己的记录
        return SportsRecord.objects.filter(user_id=user.id)

    def perform_create(self, serializer):
        user = self.request.user
        user_id = serializer.validated_data.get('user_id', user.id)

        # 管理员可以为任意用户创建记录，普通用户只能为自己创建
        if user.is_admin() or user.id == user_id:
            serializer.save()
        else:
            raise ValidationError("您只能为自己创建运动记录")


@extend_schema_view(
    get=extend_schema(
        summary="获取运动记录详情",
        description="获取指定ID的运动记录详细信息",
        tags=['运动记录'],
        responses={
            200: SportsRecordSerializer,
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    put=extend_schema(
        summary="更新运动记录",
        description="完全更新运动记录信息",
        tags=['运动记录'],
        request=SportsRecordCreateSerializer,
        responses={
            200: SportsRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新运动记录",
        description="部分更新运动记录信息",
        tags=['运动记录'],
        request=SportsRecordCreateSerializer,
        responses={
            200: SportsRecordSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    ),
    delete=extend_schema(
        summary="删除运动记录",
        description="删除指定ID的运动记录",
        tags=['运动记录'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='记录不存在')
        }
    )
)
class SportsRecordDetailView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticated, IsAdminOrOwner]

    def get_serializer_class(self):
        if self.request.method in ['PUT', 'PATCH']:
            return SportsRecordCreateSerializer
        return SportsRecordSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以操作所有记录
        if user.is_admin():
            return SportsRecord.objects.all()
        # 普通用户只能操作自己的记录
        return SportsRecord.objects.filter(user_id=user.id)


# 获取当前用户的所有记录的API
@extend_schema(
    summary="获取当前用户的所有身体指标记录",
    description="返回当前认证用户的所有身体指标记录信息",
    tags=['身体指标记录'],
    responses={
        200: BodyRecordSerializer(many=True),
        401: OpenApiResponse(description='未认证')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def my_body_records(request):
    records = BodyRecord.objects.filter(user_id=request.user.id)
    serializer = BodyRecordSerializer(records, many=True)
    return Response(serializer.data)


@extend_schema(
    summary="获取当前用户的所有饮食记录",
    description="返回当前认证用户的所有饮食记录信息",
    tags=['饮食记录'],
    responses={
        200: EatingRecordSerializer(many=True),
        401: OpenApiResponse(description='未认证')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def my_eating_records(request):
    records = EatingRecord.objects.filter(user_id=request.user.id)
    serializer = EatingRecordSerializer(records, many=True)
    return Response(serializer.data)


@extend_schema(
    summary="获取当前用户的所有睡眠记录",
    description="返回当前认证用户的所有睡眠记录信息",
    tags=['睡眠记录'],
    responses={
        200: SleepRecordSerializer(many=True),
        401: OpenApiResponse(description='未认证')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def my_sleep_records(request):
    records = SleepRecord.objects.filter(user_id=request.user.id)
    serializer = SleepRecordSerializer(records, many=True)
    return Response(serializer.data)


@extend_schema(
    summary="获取当前用户的所有运动记录",
    description="返回当前认证用户的所有运动记录信息",
    tags=['运动记录'],
    responses={
        200: SportsRecordSerializer(many=True),
        401: OpenApiResponse(description='未认证')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def my_sports_records(request):
    records = SportsRecord.objects.filter(user_id=request.user.id)
    serializer = SportsRecordSerializer(records, many=True)
    return Response(serializer.data)


@extend_schema_view(
    get=extend_schema(
        summary="获取定时任务列表",
        description="管理员获取所有定时任务列表",
        tags=['定时任务管理'],
        responses={200: ScheduledTaskSerializer(many=True)}
    ),
    post=extend_schema(
        summary="创建定时任务",
        description="管理员创建新的定时任务",
        tags=['定时任务管理'],
        request=ScheduledTaskSerializer,
        responses={201: ScheduledTaskSerializer}
    )
)
class ScheduledTaskListView(generics.ListCreateAPIView):
    queryset = ScheduledTask.objects.all()
    serializer_class = ScheduledTaskSerializer
    permission_classes = [IsAdminUser]

@extend_schema_view(
    get=extend_schema(
        summary="获取定时任务详情",
        description="管理员获取指定定时任务的详细信息",
        tags=['定时任务管理'],
        responses={200: ScheduledTaskSerializer}
    ),
    put=extend_schema(
        summary="更新定时任务",
        description="管理员更新定时任务信息",
        tags=['定时任务管理'],
        request=ScheduledTaskSerializer,
        responses={200: ScheduledTaskSerializer}
    ),
    patch=extend_schema(
        summary="部分更新定时任务",
        description="管理员部分更新定时任务信息",
        tags=['定时任务管理'],
        request=ScheduledTaskSerializer,
        responses={200: ScheduledTaskSerializer}
    ),
    delete=extend_schema(
        summary="删除定时任务",
        description="管理员删除指定的定时任务",
        tags=['定时任务管理'],
        responses={204: OpenApiResponse(description='删除成功')}
    )
)
class ScheduledTaskDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = ScheduledTask.objects.all()
    serializer_class = ScheduledTaskSerializer
    permission_classes = [IsAdminUser]

@extend_schema_view(
    post=extend_schema(
        summary="手动执行定时任务",
        description="管理员手动执行指定的定时任务",
        tags=['定时任务管理'],
        responses={200: OpenApiResponse(description='任务执行成功')}
    )
)
class ScheduledTaskExecuteView(views.APIView):
    permission_classes = [IsAdminUser]

    def post(self, request, pk):
        try:
            task = ScheduledTask.objects.get(pk=pk)
            # 根据任务类型执行相应的任务
            if task.task_type == 'news_crawler':
                from ...services.spider import news_crawler
                from .tasks import news_crawler_task
                # 使用 Celery 异步执行任务
                news_crawler_task.delay()
                task.last_run = timezone.now()
                task.save()
                return Response({'message': '健康资讯爬虫已加入执行队列'})
            elif task.task_type == 'words_crawler':
                from ...services.spider import words_crawler
                # 使用 Celery 异步执行任务
                words_crawler_task.delay()
                task.last_run = timezone.now()
                task.save()
                return Response({'message': '敏感词更新已加入执行队列'})
            elif task.task_type == 'post_review':
                # 帖子审核任务类型，可以用于批量审核等操作
                return Response({'message': '帖子审核任务执行成功'})
            elif task.task_type == 'daily_health_analysis':
                # 每日健康分析任务类型
                # 使用 Celery 异步执行任务
                daily_health_analysis_task.delay()
                task.last_run = timezone.now()
                task.save()
                return Response({'message': '每日健康分析已加入执行队列'})
            else:
                return Response({'error': '未知的任务类型'}, status=400)
        except ScheduledTask.DoesNotExist:
            return Response({'error': '任务不存在'}, status=404)

@extend_schema_view(
    get=extend_schema(
        summary="获取健康资讯列表",
        description="获取所有健康资讯文章列表",
        tags=['健康资讯'],
        responses={
            200: OpenApiResponse(
                response=HealthNewsSerializer(many=True),
                description='健康资讯列表'
            ),
            401: OpenApiResponse(description='未认证')
        }
    )
)
class HealthNewsListView(generics.ListAPIView):
    """
    健康资讯列表视图
    """
    queryset = HealthNews.objects.all().order_by('-publish_time')
    serializer_class = HealthNewsSerializer
    permission_classes = [permissions.AllowAny]  # 允许任何人
    
    # 自定义分页类，设置每页显示20条记录
    class CustomPageNumberPagination(PageNumberPagination):
        page_size = 20
        page_size_query_param = 'page_size'
        max_page_size = 100
    
    pagination_class = CustomPageNumberPagination


@extend_schema_view(
    get=extend_schema(
        summary="获取敏感词列表",
        description="管理员获取所有敏感词列表",
        tags=['敏感词管理'],
        responses={
            200: OpenApiResponse(
                response=SensitiveWordSerializer(many=True),
                description='敏感词列表'
            ),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    ),
    post=extend_schema(
        summary="创建敏感词",
        description="管理员创建新的敏感词",
        tags=['敏感词管理'],
        request=SensitiveWordCreateSerializer,
        responses={
            201: OpenApiResponse(
                response=SensitiveWordSerializer,
                description='敏感词创建成功'
            ),
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    )
)
class SensitiveWordListCreateView(generics.ListCreateAPIView):
    """
    敏感词列表和创建视图
    """
    queryset = SensitiveWord.objects.all()
    permission_classes = [IsAdminUser]
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return SensitiveWordCreateSerializer
        return SensitiveWordSerializer

    def get_queryset(self):
        queryset = SensitiveWord.objects.all()
        # 支持按分类筛选
        category = self.request.query_params.get('category', None)
        if category:
            queryset = queryset.filter(category=category)
        # 支持按关键词搜索
        keyword = self.request.query_params.get('keyword', None)
        if keyword:
            queryset = queryset.filter(word__icontains=keyword)
        return queryset

@extend_schema_view(
    get=extend_schema(
        summary="获取敏感词详情",
        description="管理员获取指定敏感词的详细信息",
        tags=['敏感词管理'],
        responses={
            200: OpenApiResponse(
                response=SensitiveWordSerializer,
                description='敏感词详情'
            ),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='敏感词不存在')
        }
    ),
    put=extend_schema(
        summary="更新敏感词",
        description="管理员更新敏感词信息",
        tags=['敏感词管理'],
        request=SensitiveWordCreateSerializer,
        responses={
            200: OpenApiResponse(
                response=SensitiveWordSerializer,
                description='敏感词更新成功'
            ),
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='敏感词不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新敏感词",
        description="管理员部分更新敏感词信息",
        tags=['敏感词管理'],
        request=SensitiveWordCreateSerializer,
        responses={
            200: OpenApiResponse(
                response=SensitiveWordSerializer,
                description='敏感词更新成功'
            ),
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='敏感词不存在')
        }
    ),
    delete=extend_schema(
        summary="删除敏感词",
        description="管理员删除指定的敏感词",
        tags=['敏感词管理'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='敏感词不存在')
        }
    )
)
class SensitiveWordDetailView(generics.RetrieveUpdateDestroyAPIView):
    """
    敏感词详情、更新、删除视图
    """
    queryset = SensitiveWord.objects.all()
    serializer_class = SensitiveWordSerializer
    permission_classes = [IsAdminUser]

    def get_serializer_class(self):
        if self.request.method in ['PUT', 'PATCH']:
            return SensitiveWordCreateSerializer
        return SensitiveWordSerializer


@extend_schema_view(
    get=extend_schema(
        summary="获取帖子列表",
        description="管理员可以看到所有帖子，普通用户只能看到自己的帖子",
        tags=['帖子'],
        responses={
            200: PostSerializer(many=True),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足')
        }
    ),
    post=extend_schema(
        summary="创建帖子",
        description="用户创建新帖子",
        tags=['帖子'],
        request=PostCreateSerializer,
        responses={
            201: PostSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
        }
    )
)
class PostListCreateView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return PostCreateSerializer
        return PostSerializer

    def get_queryset(self):
        user = self.request.user
        queryset = Post.objects.all()
        
        # 如果是管理员，可以访问所有非草稿帖子，以及自己创建的草稿帖子
        if user.is_admin():
            return queryset.filter(
                models.Q(status__in=['published', 'hidden', 'deleted', 'locked', 'banned', 'review']) |
                models.Q(status='draft', user_id=user.id)
            )
        # 普通用户只能访问自己的帖子
        else:
            return queryset.filter(user_id=user.id)

    def perform_create(self, serializer):
        user = self.request.user
        content = serializer.validated_data.get('content', '')
        title = serializer.validated_data.get('title', '')
        status = serializer.validated_data.get('status', 'published')
        
        # 普通用户只能选择草稿和发布两种状态
        if not user.is_admin() and status not in ['draft', 'published']:
            from rest_framework.exceptions import ValidationError
            raise ValidationError("普通用户只能选择草稿或发布状态")
        
        # 如果是发布状态，需要进行审核
        if status == 'published':
            # 先保存为审核状态
            instance = serializer.save(user_id=user.id, status='review')
            
            # 异步执行审核任务
            from .tasks import review_post_task
            review_post_task.delay(instance.id)
        else:
            # 草稿状态直接保存，不进行敏感词检测
            instance = serializer.save(user_id=user.id)
        
        # 保存实例以便在create方法中使用
        self.created_instance = instance

    def create(self, request, *args, **kwargs):
        """重写create方法，返回完整的帖子信息"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        
        # 使用PostSerializer返回完整的帖子信息
        post_serializer = PostSerializer(self.created_instance, context={'request': request})
        headers = self.get_success_headers(post_serializer.data)
        return Response(post_serializer.data, status=status.HTTP_201_CREATED, headers=headers)


@extend_schema_view(
    get=extend_schema(
        summary="获取帖子详情",
        description="获取指定ID的帖子详细信息及评论",
        tags=['帖子'],
        responses={
            200: PostSerializer,
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='帖子不存在')
        }
    ),
    put=extend_schema(
        summary="更新帖子",
        description="完全更新帖子信息",
        tags=['帖子'],
        request=PostCreateSerializer,
        responses={
            200: PostSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='帖子不存在')
        }
    ),
    patch=extend_schema(
        summary="部分更新帖子",
        description="部分更新帖子信息",
        tags=['帖子'],
        request=PostCreateSerializer,
        responses={
            200: PostSerializer,
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='帖子不存在')
        }
    ),
    delete=extend_schema(
        summary="删除帖子",
        description="删除指定ID的帖子及其所有评论",
        tags=['帖子'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            403: OpenApiResponse(description='权限不足'),
            404: OpenApiResponse(description='帖子不存在')
        }
    )
)
class PostDetailView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticated, IsAdminOrOwner]

    def get_serializer_class(self):
        if self.request.method in ['PUT', 'PATCH']:
            return PostCreateSerializer
        return PostSerializer

    def get_queryset(self):
        user = self.request.user
        # 管理员可以操作所有帖子
        if user.is_admin():
            return Post.objects.all()
        # 普通用户只能操作自己的帖子
        return Post.objects.filter(user_id=user.id)

    def update(self, request, *args, **kwargs):
        # 管理员可以审核帖子状态
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        
        # 获取更新后的状态
        new_status = request.data.get('status', instance.status)
        content = serializer.validated_data.get('content', instance.content)
        title = serializer.validated_data.get('title', instance.title)
        
        # 只有在帖子发布时才进行敏感词检测
        if new_status == 'published' and instance.status != 'published':
            # 检查标题和内容中的敏感词
            has_sensitive_title, sensitive_title_words = check_sensitive_words(title)
            has_sensitive_content, sensitive_content_words = check_sensitive_words(content)

            if has_sensitive_title or has_sensitive_content:
                sensitive_words = list(set(sensitive_title_words + sensitive_content_words))
                error_msg = f"内容包含敏感词: {', '.join(sensitive_words)}"
                logger.warning(f"用户 {request.user.username} 发布帖子时包含敏感词: {error_msg}")
                raise ValidationError({
                    'message': error_msg,
                    'sensitive_words': sensitive_words
                })
        
        # 如果是状态更新且用户是管理员，记录日志
        if 'status' in request.data and request.user.is_admin():
            old_status = instance.status
            new_status = request.data['status']
            logger.info(f"管理员 {request.user.username} 将帖子 {instance.id} 状态从 {old_status} 更新为 {new_status}")
        
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)


@extend_schema(
    summary="上传图片",
    description="上传图片文件",
    tags=['文件上传'],
    request={
        'multipart/form-data': {
            'type': 'object',
            'properties': {
                'image': {
                    'type': 'string',
                    'format': 'binary'
                }
            }
        }
    },
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',
                'properties': {
                    'url': {'type': 'string'}
                }
            },
            description='上传成功'
        ),
        400: OpenApiResponse(description='请求参数错误')
    }
)
class ImageUploadView(views.APIView):
    """
    图片上传视图
    """
    permission_classes = [permissions.IsAuthenticated]
    parser_classes = (MultiPartParser, FormParser)

    def post(self, request, *args, **kwargs):
        # 检查是否有文件上传
        if 'image' not in request.FILES:
            return Response({'error': '没有上传文件'}, status=status.HTTP_400_BAD_REQUEST)
        
        image_file = request.FILES['image']
        
        # 验证文件类型
        allowed_extensions = ['.jpg', '.jpeg', '.png', '.gif']
        ext = os.path.splitext(image_file.name)[1].lower()
        if ext not in allowed_extensions:
            return Response({'error': '不支持的文件类型'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 验证文件大小 (5MB)
        if image_file.size > 5 * 1024 * 1024:
            return Response({'error': '文件大小不能超过5MB'}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # 生成文件名
            filename = f"{request.user.id}_{int(timezone.now().timestamp())}{ext}"
            # 保存文件到media目录
            path = default_storage.save(f'uploads/{filename}', ContentFile(image_file.read()))
            # 获取文件URL
            url = default_storage.url(path)
            
            # 返回完整URL
            full_url = request.build_absolute_uri(url)
            
            return Response({
                'url': full_url
            }, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({'error': f'上传失败: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@extend_schema(
    summary="获取系统统计数据",
    description="管理员获取系统统计数据，包括用户总数、管理员数量",
    tags=['系统统计'],
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',                'properties': {
                    'userCount': {'type': 'integer'},
                    'adminCount': {'type': 'integer'}
                }
            },
            description='系统统计数据'
        ),
        401: OpenApiResponse(description='未认证'),
        403: OpenApiResponse(description='权限不足')
    }
)
@api_view(['GET'])
@permission_classes([IsAdminUser])
def admin_dashboard_stats(request):
    """
    管理员仪表板统计数据接口
    """
    from ..users.models import User
    
    # 统计用户总数
    user_count = User.objects.count()
    # 统计管理员数量
    admin_count = User.objects.filter(user_type='admin').count()
    
    stats = {
        'userCount': user_count,
        'adminCount': admin_count
    }
    
    return Response(stats)


@extend_schema(
    summary="获取敏感词分类列表",
    description="获取所有敏感词分类",
    tags=['敏感词管理'],
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',
                'properties': {
                    'categories': {
                        'type': 'array',
                        'items': {'type': 'string'}
                    }
                }
            },
            description='敏感词分类列表'
        ),
        401: OpenApiResponse(description='未认证'),
        403: OpenApiResponse(description='权限不足')
    }
)
@api_view(['GET'])
@permission_classes([IsAdminUser])
def sensitive_word_categories(request):
    """
    获取敏感词分类列表接口
    """
    # 从数据库中获取所有不同的分类
    categories = SensitiveWord.objects.values_list('category', flat=True).distinct().order_by('category')
    return Response({'categories': list(categories)})


@extend_schema_view(
    get=extend_schema(
        summary="获取所有已发布帖子列表",
        description="普通用户获取所有已发布的帖子列表，支持搜索",
        tags=['帖子'],
        responses={
            200: PostSerializer(many=True),
            401: OpenApiResponse(description='未认证')
        }
    )
)
class PublicPostListView(generics.ListAPIView):
    """
    公开帖子列表视图 - 供普通用户查看所有已发布的帖子
    """
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_queryset(self):
        """
        返回所有已发布的帖子，支持搜索功能
        """
        # 只返回已发布的帖子
        queryset = Post.objects.filter(status='published')
        
        # 支持标题和内容搜索
        search = self.request.query_params.get('search', None)
        if search:
            queryset = queryset.filter(
                models.Q(title__icontains=search) | 
                models.Q(content__icontains=search)
            )
        
        return queryset.order_by('-created_at')


@extend_schema_view(
    post=extend_schema(
        summary="收藏帖子",
        description="用户收藏指定的帖子",
        tags=['帖子收藏'],
        request=None,
        responses={
            201: OpenApiResponse(description='收藏成功'),
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            404: OpenApiResponse(description='帖子不存在')
        }
    )
)
class PostFavoriteCreateView(generics.CreateAPIView):
    """
    帖子收藏创建视图
    """
    permission_classes = [permissions.IsAuthenticated]

    def create(self, request, *args, **kwargs):
        user = request.user
        post_id = kwargs.get('post_id')
        
        try:
            post = Post.objects.get(id=post_id, status='published')
        except Post.DoesNotExist:
            return Response({'error': '帖子不存在或未发布'}, status=status.HTTP_404_NOT_FOUND)
        
        # 创建收藏记录
        favorite, created = PostFavorite.objects.get_or_create(
            user_id=user.id,
            post=post
        )
        
        if created:
            return Response({'message': '收藏成功'}, status=status.HTTP_201_CREATED)
        else:
            return Response({'message': '已收藏'}, status=status.HTTP_200_OK)


@extend_schema_view(
    delete=extend_schema(
        summary="取消收藏帖子",
        description="用户取消收藏指定的帖子",
        tags=['帖子收藏'],
        responses={
            204: OpenApiResponse(description='取消收藏成功'),
            401: OpenApiResponse(description='未认证'),
            404: OpenApiResponse(description='收藏记录不存在')
        }
    )
)
class PostFavoriteDeleteView(generics.DestroyAPIView):
    """
    帖子收藏删除视图
    """
    permission_classes = [permissions.IsAuthenticated]

    def get_object(self):
        user = self.request.user
        post_id = self.kwargs.get('post_id')
        
        try:
            return PostFavorite.objects.get(user_id=user.id, post_id=post_id)
        except PostFavorite.DoesNotExist:
            return None

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance is None:
            return Response({'error': '收藏记录不存在'}, status=status.HTTP_404_NOT_FOUND)
        
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)


@extend_schema_view(
    get=extend_schema(
        summary="获取用户收藏的帖子列表",
        description="获取当前用户收藏的所有帖子列表",
        tags=['帖子收藏'],
        responses={
            200: PostFavoriteSerializer(many=True),
            401: OpenApiResponse(description='未认证')
        }
    )
)
class PostFavoriteListView(generics.ListAPIView):
    """
    用户收藏的帖子列表视图
    """
    serializer_class = PostFavoriteSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = PageNumberPagination

    def get_queryset(self):
        user = self.request.user
        return PostFavorite.objects.filter(user_id=user.id).select_related('post').order_by('-created_at')


@extend_schema_view(
    post=extend_schema(
        summary="点赞/踩帖子",
        description="用户对指定帖子进行点赞或点踩操作",
        tags=['帖子点赞'],
        request={
            'application/json': {
                'type': 'object',
                'properties': {
                    'like_type': {
                        'type': 'integer',
                        'enum': [1, -1],
                        'description': '1表示点赞，-1表示点踩'
                    }
                },
                'required': ['like_type']
            }
        },
        responses={
            201: OpenApiResponse(description='操作成功'),
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
            404: OpenApiResponse(description='帖子不存在')
        }
    )
)
class PostLikeCreateView(generics.CreateAPIView):
    """
    帖子点赞/踩创建视图
    """
    permission_classes = [permissions.IsAuthenticated]

    def create(self, request, *args, **kwargs):
        user = request.user
        post_id = kwargs.get('post_id')
        
        try:
            post = Post.objects.get(id=post_id, status='published')
        except Post.DoesNotExist:
            return Response({'error': '帖子不存在或未发布'}, status=status.HTTP_404_NOT_FOUND)
        
        # 获取操作类型 (1: 点赞, -1: 点踩)
        like_type = request.data.get('like_type')
        if like_type not in [1, -1]:
            return Response({'error': '无效的操作类型'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 创建或更新点赞记录
        like, created = PostLike.objects.update_or_create(
            user_id=user.id,
            post=post,
            defaults={'like_type': like_type}
        )
        
        if created:
            message = '点赞成功' if like_type == 1 else '点踩成功'
            return Response({'message': message}, status=status.HTTP_201_CREATED)
        else:
            message = '更新操作成功'
            return Response({'message': message}, status=status.HTTP_200_OK)


@extend_schema_view(
    delete=extend_schema(
        summary="取消点赞/踩",
        description="用户取消对指定帖子的点赞或点踩",
        tags=['帖子点赞'],
        responses={
            204: OpenApiResponse(description='取消操作成功'),
            401: OpenApiResponse(description='未认证'),
            404: OpenApiResponse(description='点赞记录不存在')
        }
    )
)
class PostLikeDeleteView(generics.DestroyAPIView):
    """
    帖子点赞/踩删除视图
    """
    permission_classes = [permissions.IsAuthenticated]

    def get_object(self):
        user = self.request.user
        post_id = self.kwargs.get('post_id')
        
        try:
            return PostLike.objects.get(user_id=user.id, post_id=post_id)
        except PostLike.DoesNotExist:
            return None

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance is None:
            return Response({'error': '点赞记录不存在'}, status=status.HTTP_404_NOT_FOUND)
        
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)


@extend_schema(
    summary="获取帖子的收藏和点赞状态",
    description="获取当前用户对指定帖子的收藏和点赞状态",
    tags=['帖子'],
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',
                'properties': {
                    'is_favorited': {'type': 'boolean'},
                    'like_type': {'type': 'integer', 'nullable': True}
                }
            },
            description='状态信息'
        ),
        401: OpenApiResponse(description='未认证'),
        404: OpenApiResponse(description='帖子不存在')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def post_user_status(request, post_id):
    """
    获取用户对帖子的收藏和点赞状态
    """
    user = request.user
    
    try:
        post = Post.objects.get(id=post_id, status='published')
    except Post.DoesNotExist:
        return Response({'error': '帖子不存在或未发布'}, status=status.HTTP_404_NOT_FOUND)
    
    # 检查是否已收藏
    is_favorited = PostFavorite.objects.filter(user_id=user.id, post=post).exists()
    
    # 获取点赞状态
    try:
        like = PostLike.objects.get(user_id=user.id, post=post)
        like_type = like.like_type
    except PostLike.DoesNotExist:
        like_type = None
    
    return Response({
        'is_favorited': is_favorited,
        'like_type': like_type
    })


@extend_schema(
    summary="获取帖子的统计信息",
    description="获取指定帖子的收藏数、点赞数和点踩数",
    tags=['帖子'],
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',
                'properties': {
                    'favorites_count': {'type': 'integer'},
                    'likes_count': {'type': 'integer'},
                    'dislikes_count': {'type': 'integer'}
                }
            },
            description='统计信息'
        ),
        404: OpenApiResponse(description='帖子不存在')
    }
)
@api_view(['GET'])
def post_stats(request, post_id):
    """
    获取帖子的统计信息
    """
    try:
        post = Post.objects.get(id=post_id, status='published')
    except Post.DoesNotExist:
        return Response({'error': '帖子不存在或未发布'}, status=status.HTTP_404_NOT_FOUND)
    
    # 统计收藏数
    favorites_count = PostFavorite.objects.filter(post=post).count()
    
    # 统计点赞数和点踩数
    likes_count = PostLike.objects.filter(post=post, like_type=1).count()
    dislikes_count = PostLike.objects.filter(post=post, like_type=-1).count()
    
    return Response({
        'favorites_count': favorites_count,
        'likes_count': likes_count,
        'dislikes_count': dislikes_count
    })


@extend_schema(
    summary="获取用户健康数据统计",
    description="获取当前认证用户的健康数据统计信息，包括各类记录的数量",
    tags=['健康数据'],
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',
                'properties': {
                    'bodyRecordCount': {'type': 'integer'},
                    'eatingRecordCount': {'type': 'integer'},
                    'sleepRecordCount': {'type': 'integer'},
                    'sportsRecordCount': {'type': 'integer'}
                }
            },
            description='用户健康数据统计信息'
        ),
        401: OpenApiResponse(description='未认证')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def user_health_stats(request):
    """
    获取当前认证用户的健康数据统计信息 - 优化版本
    """
    start_time = time.time()
    user = request.user
    logger.info(f"开始获取用户 {user.id} 的健康统计数据")
    
    # 使用缓存优化性能
    cache_key = f'user_health_stats_{user.id}'
    cached_stats = cache.get(cache_key)
    
    if cached_stats:
        logger.info(f"从缓存获取用户 {user.id} 的健康统计数据")
        return Response(cached_stats)
    
    # 使用单个查询优化性能
    try:
        # 使用聚合查询一次性获取所有统计信息
        from django.db.models import Count
        
        # 分别查询各表数量（比单个复杂查询更高效）
        body_count = BodyRecord.objects.filter(user_id=user.id).count()
        eating_count = EatingRecord.objects.filter(user_id=user.id).count()
        sleep_count = SleepRecord.objects.filter(user_id=user.id).count()
        sports_count = SportsRecord.objects.filter(user_id=user.id).count()
        
        stats = {
            'bodyRecordCount': body_count,
            'eatingRecordCount': eating_count,
            'sleepRecordCount': sleep_count,
            'sportsRecordCount': sports_count
        }
        
        # 设置缓存，有效期5分钟
        cache.set(cache_key, stats, 300)
        
        total_time = time.time() - start_time
        logger.info(f"用户 {user.id} 健康统计数据查询完成，总耗时: {total_time:.4f}秒")
        
        return Response(stats)
        
    except Exception as e:
        logger.error(f"获取用户 {user.id} 健康统计数据失败: {str(e)}")
        return Response({'error': '获取统计数据失败'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# 添加体检报告相关的视图类和函数
from .models import HealthReport
from .serializers import HealthReportSerializer, HealthReportCreateSerializer


@extend_schema_view(
    get=extend_schema(
        summary="获取体检报告列表",
        description="获取当前用户的所有体检报告",
        tags=['体检报告'],
        responses={
            200: HealthReportSerializer(many=True),
            401: OpenApiResponse(description='未认证')
        }
    ),
    post=extend_schema(
        summary="上传体检报告",
        description="上传体检报告PDF文件并进行分析",
        tags=['体检报告'],
        request={
            'multipart/form-data': {
                'type': 'object',
                'properties': {
                    'file': {
                        'type': 'string',
                        'format': 'binary'
                    }
                }
            }
        },
        responses={
            201: OpenApiResponse(description='上传成功'),
            400: OpenApiResponse(description='请求参数错误'),
            401: OpenApiResponse(description='未认证'),
        }
    )
)
class HealthReportListCreateView(generics.ListCreateAPIView):
    """
    体检报告列表和创建视图
    """
    permission_classes = [permissions.IsAuthenticated]
    parser_classes = (MultiPartParser, FormParser)
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return HealthReportCreateSerializer
        return HealthReportSerializer

    def get_queryset(self):
        user = self.request.user
        return HealthReport.objects.filter(user_id=user.id).order_by('-uploaded_at')

    def create(self, request, *args, **kwargs):
        # 检查是否有文件上传
        if 'file' not in request.FILES:
            return Response({'error': '没有上传文件'}, status=status.HTTP_400_BAD_REQUEST)
        
        file = request.FILES['file']
        
        # 验证文件类型
        if not file.name.endswith('.pdf'):
            return Response({'error': '只支持PDF文件'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 验证文件大小 (10MB)
        if file.size > 10 * 1024 * 1024:
            return Response({'error': '文件大小不能超过10MB'}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # 保存文件到media目录
            filename = f"health_report_{request.user.id}_{int(timezone.now().timestamp())}.pdf"
            path = default_storage.save(f'health_reports/{filename}', ContentFile(file.read()))
            
            # 创建体检报告记录，初始状态为已上传
            health_report = HealthReport.objects.create(
                user_id=request.user.id,
                file_path=path,
                status='uploaded'  # 设置初始状态
            )
            
            # 异步执行分析任务
            try:
                from .tasks import analyze_health_report_task
                analyze_health_report_task.delay(health_report.id)
                
                # 更新状态为分析中
                health_report.status = 'analyzing'
                health_report.save()
                
            except Exception as task_error:
                # 任务启动失败，更新状态为分析失败
                health_report.status = 'failed'
                health_report.analysis_result = f"分析任务启动失败: {str(task_error)}"
                health_report.save()
                logger.error(f"Failed to start analysis task: {task_error}")
            
            return Response({
                'message': '上传成功，正在分析中...',
                'report_id': health_report.id,
                'status': health_report.status
            }, status=status.HTTP_201_CREATED)
        except Exception as e:
            return Response({'error': f'上传失败: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@extend_schema_view(
    get=extend_schema(
    summary="获取体检报告详情",
    description="获取指定ID的体检报告详情",
    tags=['体检报告'],
    responses={
        200: HealthReportSerializer,
        401: OpenApiResponse(description='未认证'),
        404: OpenApiResponse(description='体检报告不存在')
    }
    ),
    delete=extend_schema(
        summary="删除体检报告",
        description="删除指定ID的体检报告",
        tags=['体检报告'],
        responses={
            204: OpenApiResponse(description='删除成功'),
            401: OpenApiResponse(description='未认证'),
            404: OpenApiResponse(description='体检报告不存在')
        }
    )
)
class HealthReportDetailView(generics.RetrieveDestroyAPIView):
    """
    体检报告详情和删除视图
    """
    permission_classes = [permissions.IsAuthenticated]

    def get_serializer_class(self):
        return HealthReportSerializer

    def get_queryset(self):
        user = self.request.user
        return HealthReport.objects.filter(user_id=user.id)

    def retrieve(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            return Response(serializer.data)
        except HealthReport.DoesNotExist:
            return Response({'error': '体检报告不存在'}, status=status.HTTP_404_NOT_FOUND)


@extend_schema(
    summary="流式获取体检报告分析结果",
    description="流式获取指定体检报告的分析结果",
    tags=['体检报告'],
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',
                'properties': {
                    'analysis_result': {'type': 'string'}
                }
            },
            description='分析结果'
        ),
        401: OpenApiResponse(description='未认证'),
        404: OpenApiResponse(description='体检报告不存在')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def health_report_analysis_stream(request, report_id):
    """
    流式获取体检报告分析结果 - 使用SSE实现实时更新
    """
    user = request.user
    
    try:
        report = HealthReport.objects.get(id=report_id, user_id=user.id)
    except HealthReport.DoesNotExist:
        return Response({'error': '体检报告不存在'}, status=status.HTTP_404_NOT_FOUND)
    
    def event_stream():
        # 如果已经有完整的分析结果，直接返回
        if report.analysis_result and not report.analysis_result.startswith('[STREAMING]') and report.analysis_result != '':
            yield f"data: {json.dumps({'analysis_result': report.analysis_result})}\n\n"
            yield "data: [DONE]\n\n"
            return
            
        # 如果没有分析结果，触发分析任务
        if not report.analysis_result or report.analysis_result == '':
            try:
                from .tasks import analyze_health_report_task
                analyze_health_report_task.delay(report.id)
            except Exception as task_error:
                logger.error(f"Failed to start analysis task: {task_error}")
                yield f"data: {json.dumps({'analysis_result': '无法启动分析任务'})}\n\n"
                yield "data: [DONE]\n\n"
                return
        
        # 等待并流式传输分析结果
        import time
        max_wait_time = 60  # 最大等待时间60秒
        wait_time = 0
        while wait_time < max_wait_time:
            report.refresh_from_db()
            # 检查是否有完整的分析结果
            if report.analysis_result and not report.analysis_result.startswith('[STREAMING]') and report.analysis_result != '':
                yield f"data: {json.dumps({'analysis_result': report.analysis_result})}\n\n"
                yield "data: [DONE]\n\n"
                return
            time.sleep(1)
            wait_time += 1
        
        # 如果超时仍未完成分析
        yield f"data: {json.dumps({'analysis_result': '分析超时，请稍后再试'})}\n\n"
        yield "data: [DONE]\n\n"
    
    # 设置响应头以支持SSE
    response = StreamingHttpResponse(event_stream(), content_type='text/event-stream')
    response['Cache-Control'] = 'no-cache'
    response['X-Accel-Buffering'] = 'no'  # 禁用Nginx缓冲
    return response


@extend_schema(
    summary="手动触发体检报告分析",
    description="手动触发指定体检报告的分析任务",
    tags=['体检报告'],
    responses={
        200: OpenApiResponse(description='分析任务已启动'),
        401: OpenApiResponse(description='未认证'),
        404: OpenApiResponse(description='体检报告不存在')
    }
)
@api_view(['POST'])
@permission_classes([permissions.IsAuthenticated])
def trigger_health_report_analysis(request, report_id):
    """
    手动触发体检报告分析任务
    """
    import logging
    import traceback
    logger = logging.getLogger(__name__)
    user = request.user
    
    try:
        report = HealthReport.objects.get(id=report_id, user_id=user.id)
    except HealthReport.DoesNotExist:
        return Response({'error': '体检报告不存在'}, status=status.HTTP_404_NOT_FOUND)
    
    # 检查报告状态，只有 uploaded 或 failed 状态可以重新分析
    if report.status not in ['uploaded', 'failed']:
        return Response({'error': '报告当前状态无法进行分析'}, status=status.HTTP_400_BAD_REQUEST)
    
    # 更新报告状态为分析中
    report.status = 'analyzing'
    report.save()
    
    # 异步执行分析任务
    try:
        from .tasks import analyze_health_report_task
        analyze_health_report_task.delay(report.id)
        return Response({'message': '分析任务已启动'})
    except ImportError as e:
        error_msg = f"无法导入分析任务模块: {str(e)}"
        logger.error(f"{error_msg}\n{traceback.format_exc()}")
        # 任务启动失败，回滚状态
        report.status = 'failed'
        report.save()
        return Response({'error': '无法启动分析任务: 模块导入失败'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    except Exception as task_error:
        error_msg = f"Failed to start analysis task: {str(task_error)}"
        logger.error(f"{error_msg}\n{traceback.format_exc()}")
        # 任务启动失败，回滚状态
        report.status = 'failed'
        report.save()
        return Response({'error': '无法启动分析任务'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@extend_schema(
    summary="获取用户昨日健康分析",
    description="获取当前用户的昨日健康分析结果",
    tags=['健康数据'],
    responses={
        200: OpenApiResponse(
            response={
                'type': 'object',
                'properties': {
                    'analysis_result': {'type': 'string'},
                    'analysis_date': {'type': 'string', 'format': 'date'}
                }
            },
            description='分析结果'
        ),
        401: OpenApiResponse(description='未认证'),
        404: OpenApiResponse(description='未找到分析结果')
    }
)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def user_yesterday_analysis(request):
    """
    获取用户昨日健康分析 - 优化版本
    """
    user = request.user
    
    try:
        # 计算昨天的日期
        from datetime import datetime, timedelta
        yesterday = datetime.now().date() - timedelta(days=1)
        
        # 使用缓存优化性能
        cache_key = f'user_yesterday_analysis_{user.id}_{yesterday}'
        cached_result = cache.get(cache_key)
        
        if cached_result:
            logger.info(f"从缓存获取用户 {user.id} 的昨日健康分析结果")
            return Response(cached_result)
        
        # 获取用户昨日的健康分析报告
        yesterday_report = HealthReport.objects.filter(
            user_id=user.id,
            uploaded_at__date=yesterday  # 精确匹配昨天的日期
        ).exclude(analysis_result__isnull=True).exclude(analysis_result='').first()
        
        if yesterday_report and yesterday_report.analysis_result:
            result = {
                'analysis_result': yesterday_report.analysis_result,
                'analysis_date': yesterday.isoformat()
            }
            
            # 设置缓存，有效期1小时
            cache.set(cache_key, result, 3600)
            
            logger.info(f"成功获取用户 {user.id} 的昨日健康分析结果")
            return Response(result)
        else:
            logger.info(f"用户 {user.id} 的昨日健康分析结果不存在")
            return Response({
                'analysis_result': '昨日暂无健康分析数据，请确保已上传相关健康数据',
                'analysis_date': yesterday.isoformat()
            })
            
    except Exception as e:
        logger.error(f"获取用户 {user.id} 的昨日健康分析结果失败: {str(e)}")
        return Response({'error': f'获取分析结果失败: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

